#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
IOTMQ API: Publisher
'''
import urllib, urllib2
import json
import logging
from ConfigParser import ConfigParser
import zc.zk

class Publisher():
    def __init__(self, conf_path):
        '''
        init publisher api class
        '''
        try:
            self.conf = ConfigParser()
            self.conf.read(conf_path)
        except Exception, e:
            print 'read conf file failed, %s' % str(e)
            exit

        # init logger
        log_level = {}
        log_level['DEBUG'] = logging.DEBUG
        log_level['INFO'] = logging.INFO
        log_level['ERROR'] = logging.ERROR
        try:
            loglevel = log_level[self.conf.get('all', 'log-level')]
        except Exception, e:
            loglevel = logging.DEBUG

        formatstr = '%(asctime)s %(name)-8s %(levelname)-8s %(message)s'
        logging.basicConfig(level = loglevel, format = formatstr)
        self.logger = logging.getLogger('broker')
        self.logger.info('logger init OK.')

    def connect(self, user, passwd):
        '''
        connect to iot master server
        args:
            user: registered username
            passwd: passwd for username
        return:
            success, return True
            failed, return False
        '''
        meta_server = self.conf.get('all', 'meta-server')
        logging.info('find meta server address %s', meta_server)
        # init zk
        try:
            self.zk = zc.zk.ZooKeeper(meta_server)
        except Exception, e:
            logging.exception('connect to meta server failed, %s' % str(e))
            return
        # find master
        try:
            master = sorted(self.zk.children('/iotmq/master'))
            if not len(master):
                logging.error('no master running...')
                exit
            self.master = master[0]
            logging.info('find master %s', master[0])
        except Exception, e:
            logging.exception('find master error, %s' % str(e))
        # register node
        return True

    def publish(self, queue, message):
        '''
        publish message to specified message queue
        args:
            queue: queue to pub
            message: message to pub
        return:
            success, return True
            failed, return False
        '''
        last_id = None
        counter = 1
        while True:
            # find ds server
            master_uri = 'http://%s/%s/' % (self.master, queue)
            if last_id:
                master_uri = '%s%d' % (master_uri, last_id)
            logging.info('master uri: %s' % master_uri)

            data = {}
            block_info = None
            try:
                ret = urllib2.urlopen(master_uri, urllib.urlencode(data)).read()
                logging.debug('find ds server %d: %s' % (counter, ret))
                block_info = json.loads(ret)
            except Exception, e:
                logging.exception('urlopen failed, %s' % str(e))
                exit
            # pub data 
            #data_server = 'http://' + block_info['ds_group'] + '/' + queue + '/' + block_info['id'] + '/'
            data_server = "http://%s/%s/%d/" % (block_info['ds_group'], queue, block_info['id'])
            logging.debug('get data server uri: %s' % data_server)
            pub_data = {
                'data': message
            }
            try:
                ret = urllib2.urlopen(data_server, urllib.urlencode(pub_data)).read()
                pub_result = json.loads(ret)
                if pub_result['status'] == 'OK':
                    logging.debug('publish OK')
                    return True
                elif pub_result['status'] == 'BlockFull':
                    logging.info('block full, %s' % ret)
                    # need repub
                    last_id = pub_result['last-id']
                    counter += 1
                    continue
                else:
                    logging.error('publish failed')
                    return False
            except Exception, e:
                logging.exception('publish data failed, %s' % str(e))

    def disconnect(self):
        '''
        disconnect with server
        '''
        return True

if __name__ == "__main__":
    pub = Publisher('./conf/pub.conf')
    pub.connect('root', 'root')
    counter = 0
    line = 'x' * 1000
    #pub.publish('test-queue', line)
    #exit
    while counter < 2000:
        pub.publish('test-queue', line)
        logging.info('======>pub OK')

